/***************************************************************************
 *   Copyright (C) 2008 by Rysiek Król,,,   *
 *   rysiek@Babylon2   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "fileoperationshandler.h"

#include "picturemanager.h"
#include "renamedialog.h"
#include "picturelistwidgetitem.h"
#include "viewerevent.h"
#include "progressdialogevent.h"

#include <QListWidget>
#include <QProgressDialog>
#include <QDirIterator>


FileOperationsHandler::FileOperationsHandler(PictureManager* parent, FileOperationsHandler::OpreationType action, QList<QFileInfo> pliki, QString newFileName): QThread(parent)
{
	this->lista = pliki;
        this->manager = parent;
        this->action = action;
        this->newFileName = newFileName;
	this->start ( QThread::LowPriority );
}


FileOperationsHandler::~FileOperationsHandler()
{
}

void FileOperationsHandler::run()
{
        switch (this->action) {
        case FileOperationsHandler::Rename: 
                this->renameAction();
                break;
        
        case FileOperationsHandler::Copy: 
                this->copyAction();
                break;
        
        case FileOperationsHandler::Move:
                this->moveAction();
                break;
                
        case FileOperationsHandler::Delete: 
                this->deleteAction();
                break;
        
        case FileOperationsHandler::MakeDir:
                this->makeDirAction();
                break;
        case FileOperationsHandler::RemoveComments:
        	this->removeCommentsAction();
        default:
        
        break;
        }
}

/**
* Handles rename action
*/
void FileOperationsHandler::renameAction()
{
	int q = 0;
        if (this->lista.count()>0) {
                QListIterator<QFileInfo> iterator(this->lista);
                iterator.toFront();
                QFileInfo fileInfo =iterator.next();
                QDir dir = fileInfo.absolutePath();
                iterator.toFront();
                //int count = 1;
                while (iterator.hasNext()) {
                        QFileInfo fileInfo = iterator.next();
                        if (!fileInfo.isDir()) {
                                if (this->lista.count()==1) {
                                        QString string(this->newFileName+"."+fileInfo.completeSuffix());
                                        dir.rename(fileInfo.fileName(), string);
                                        if (dir.cd(".comments")) {
                                                string = this->newFileName+"."+fileInfo.completeSuffix()+".xml";
                                                dir.rename(fileInfo.fileName()+".xml", string);
                                                dir.cdUp();
                                        }
                                } else {
                                        QString string(this->newFileName+"_"+QString::number(q+1)+"."+fileInfo.completeSuffix());
                                        dir.rename(fileInfo.fileName(), string);
                                        if (dir.cd(".comments")) {
                                                string = this->newFileName+"_"+QString::number(q+1)+"."+fileInfo.completeSuffix()+".xml";
                                                dir.rename(fileInfo.fileName()+".xml", string);
                                                dir.cdUp();
                                                q++;
                                        }
                                }
                        }
                }
                QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
        }
}

/**
* Handles delete action
*/
void FileOperationsHandler::deleteAction()
{
	if (this->lista.count()>0){
		QListIterator<QFileInfo> iterator(this->lista);
		iterator.toFront();
		QFileInfo fileInfo = iterator.next();
		QDir dir = fileInfo.absolutePath();
		bool isDirComments =  dir.cd(".comments");
		iterator.toFront();
		int count=1;
		while(iterator.hasNext()){
			QFileInfo fileInfo = iterator.next();
			ProgressDialogEvent *event = new ProgressDialogEvent(this, count++, this->lista.count(), ProgressDialogEvent::DeleteFiles, fileInfo.fileName() );
			QApplication::postEvent ( manager, event );
			if (!fileInfo.isDir()){
				QFile file(fileInfo.absoluteFilePath());
				file.remove();
				if (isDirComments) dir.remove(fileInfo.fileName()+ ".xml");
			} else {
				this->removeDirectory(QDir(fileInfo.absoluteFilePath()));
			} 
		}
	QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
	}
}


/**
* Handles Copy action
*/
void FileOperationsHandler::copyAction()
{
	makeFileList();
        if (this->lista.count()>0) {
                QListIterator<QFileInfo> iterator(this->lista);
                QDir baseSourceDir(iterator.next().absolutePath());
                QDir baseTargetDir(this->newFileName);
                QDir commentSourceDir;
                QDir commentTargetDir;
                iterator.toFront();
                int count=1;
                while (iterator.hasNext()) {
                        QFileInfo fileInfo = iterator.next();
                        ProgressDialogEvent *event = new ProgressDialogEvent(this, count++, this->lista.count(), ProgressDialogEvent::CopyFiles, fileInfo.fileName() );
                        QApplication::postEvent ( manager, event );
                        if (fileInfo.isDir()) {
                                baseTargetDir.mkdir(baseSourceDir.relativeFilePath(fileInfo.absoluteFilePath()));
                        } else {
                                QString target = baseTargetDir.absoluteFilePath(baseSourceDir.relativeFilePath(fileInfo.absoluteFilePath()));
                                this->copyFiles(fileInfo.absoluteFilePath(), target);
                                commentSourceDir.cd(fileInfo.absolutePath());
                                if (commentSourceDir.cd(".comments")) {
                                        commentTargetDir.cd(this->newFileName);
                                        commentTargetDir.cd(baseSourceDir.relativeFilePath(fileInfo.absolutePath()));
                                        commentTargetDir.mkdir(".comments");
                                        if (commentTargetDir.cd(".comments")) {
                                                this->copyFiles(commentSourceDir.absoluteFilePath(fileInfo.fileName()+".xml"), commentTargetDir.absoluteFilePath(fileInfo.fileName()+".xml"));
                                        }
                                }
                        }
                }
        }
}

/**
* Handles move action
*/
void FileOperationsHandler::moveAction()
{
	makeFileList();
        if (this->lista.count()>0) {
                QListIterator<QFileInfo> iterator(this->lista);
                QDir baseSourceDir(iterator.next().absolutePath());
                QDir baseTargetDir(this->newFileName);
                QDir commentSourceDir;
                QDir commentTargetDir;
                iterator.toFront();
                int count=1;
                while (iterator.hasNext()) {
                        QFileInfo fileInfo = iterator.next();
                        ProgressDialogEvent *event = new ProgressDialogEvent(this, count++, this->lista.count(), ProgressDialogEvent::MoveFiles, fileInfo.fileName() );
                        QApplication::postEvent ( manager, event );
                        if (fileInfo.isDir()) {
                                baseTargetDir.mkdir(baseSourceDir.relativeFilePath(fileInfo.absoluteFilePath()));
                        } else {
                                QString target = baseTargetDir.absoluteFilePath(baseSourceDir.relativeFilePath(fileInfo.absoluteFilePath()));
                                if (this->copyFiles(fileInfo.absoluteFilePath(), target)) QFile(fileInfo.absoluteFilePath()).remove();
                                commentSourceDir.cd(fileInfo.absolutePath());
                                if (commentSourceDir.cd(".comments")) {
                                        commentTargetDir.cd(this->newFileName);
                                        commentTargetDir.cd(baseSourceDir.relativeFilePath(fileInfo.absolutePath()));
                                        commentTargetDir.mkdir(".comments");
                                        if (commentTargetDir.cd(".comments")) {
                                                if (this->copyFiles(commentSourceDir.absoluteFilePath(fileInfo.fileName()+".xml"), commentTargetDir.absoluteFilePath(fileInfo.fileName()+".xml"))) 
                                                QFile(commentSourceDir.absoluteFilePath(fileInfo.fileName()+".xml")).remove() ;
                                        }
                                }
                        }
                }
                iterator.toBack();
                while(iterator.hasPrevious()){
                	QFileInfo fileInfo = iterator.previous();
                	if (fileInfo.isDir()) {
                		QDir(fileInfo.absoluteFilePath()).rmdir(".comments");
                		QDir(fileInfo.absolutePath()).rmdir(fileInfo.fileName()); 
                	}
                }
	QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
        }
}

/**
* Copying files
*/
bool FileOperationsHandler::copyFiles(QString fromFile, QString toFile)
{
	bool result = false;
	int outBytesCount = 0;
	int inBytesCount = 0;
	
         QFile fileOut(fromFile);
         fileOut.open(QIODevice::ReadOnly);
         fileOut.waitForReadyRead(-1);
         fileOut.waitForBytesWritten(-1);
         QDataStream out(&fileOut);
         char *s = new char[fileOut.size()];
         outBytesCount = out.readRawData(s,fileOut.size());

         fileOut.close();
	 QFile fileIn(toFile);
         fileIn.open(QIODevice::WriteOnly);
         fileIn.waitForReadyRead(-1);
         fileIn.waitForBytesWritten(-1);
         QDataStream in(&fileIn);
         inBytesCount = in.writeRawData(s, fileOut.size());

         fileIn.close();
         if (outBytesCount==inBytesCount) result = true;
         delete s;
         return result;
}

/**
* Makes New Directory
*/
void FileOperationsHandler::makeDirAction()
{
        QDir *curDir = this->manager->getCurDir();
        curDir->mkdir(this->newFileName);
        QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
}

void FileOperationsHandler::removeCommentsAction()
{
	if (this->lista.count()>0){
		QListIterator<QFileInfo> iterator(this->lista);
		iterator.toFront();
		QFileInfo fileInfo = iterator.next();
		QDir dir = fileInfo.absolutePath();
		bool isDirComments =  dir.cd(".comments");
		iterator.toFront();
                int count=1;
		while(iterator.hasNext()){
			QFileInfo fileInfo = iterator.next();
			ProgressDialogEvent *event = new ProgressDialogEvent(this, count++, this->lista.count(), ProgressDialogEvent::RemoveComments, fileInfo.fileName() );
			QApplication::postEvent ( manager, event );
			if (isDirComments) dir.remove(fileInfo.fileName()+".xml");
		}
	QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ForceReload ) ) );
	}
}
/**
* Removes directory along witch all contents
*/
void FileOperationsHandler::removeDirectory(QDir dir)
{
        dir.setFilter(QDir::Dirs|QDir::NoDotAndDotDot|QDir::Hidden|QDir::System|QDir::Files);
        if (dir.count()>0) {
                QDirIterator iterator(dir);
                while (iterator.hasNext()) {
                        QFileInfo fileInfo(iterator.next());
                        QString nazwa = fileInfo.fileName();
                        if (fileInfo.isDir()) {
                                this->removeDirectory(QDir(fileInfo.absoluteFilePath()));
                        } else {
                                dir.remove(fileInfo.fileName());
                        }
                }
        } 
                QString name = dir.absolutePath();
                dir.cdUp();
                dir.rmdir(name);
}

/**
* Makes File List to copy/move
*/
void FileOperationsHandler::makeFileList()
{
QList<QFileInfo> tmp = this->lista;
this->lista.clear();
QListIterator<QFileInfo> iterator(tmp);
QFileInfo fileInfo;
	while(iterator.hasNext()){
	fileInfo = iterator.next();
		if (fileInfo.isDir()){
			this->lista.append(fileInfo);
			this->addDirToList(QDir(fileInfo.absoluteFilePath()));
		}else{
			this->lista.append(fileInfo);
		}
	}
}

/**
* Adds files from directory fo the list
*/
void FileOperationsHandler::addDirToList(QDir dir)
{
        dir.setFilter(QDir::AllDirs|QDir::NoDotAndDotDot|QDir::Files);
        QStringList filters;
        filters << "*.jpg" << "*.png" << "*.bmp"<<"*.jpeg"<<"*.JPG"<<"*.JPEG";
        dir.setNameFilters(filters);
        QDirIterator iterator(dir);
        QFileInfo fileInfo;
        while (iterator.hasNext()) {
                fileInfo = iterator.next();
                if (fileInfo.isDir()) {
                	this->lista.append(fileInfo);
                        this->addDirToList(QDir(fileInfo.absoluteFilePath()));
                } else {
                        this->lista.append(fileInfo);
                }
        }

}






